package frame.options.simulation.create.physicalNetworks;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.SystemColor;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionListener;





import model.components.networks.network.PhysicalNetwork;

@SuppressWarnings("serial")
public class PhysicalNetworksPanel extends JPanel
{
	public static final String AVAILABLE_LIST = "AvailableList";
	
	public static final String ADD_BUTTON = "Add";
	public static final String ADD_ALL_BUTTON = "AddAll";
	
	public static final String REMOVE_BUTTON = "Remove";
	public static final String REMOVE_ALL_BUTTON = "RemoveAll";
	
	public static final String SELECTED_LIST = "SelectedList";
	
	private JList< PhysicalNetwork > availablePhysicalNetworksList;
	public JList< PhysicalNetwork > getAvailablePhysicalNetworksList(){ return availablePhysicalNetworksList; }
	public void setAvailablePhysicalNetworksList( JList< PhysicalNetwork > availablePhysicalNetworksList ){ this.availablePhysicalNetworksList = availablePhysicalNetworksList; }
	
	private DefaultListModel< PhysicalNetwork > availablePhysicalNetworksListModel;
	public DefaultListModel< PhysicalNetwork > getAvailablePhysicalNetworksListModel(){ return this.availablePhysicalNetworksListModel; }
	public void setAvailablePhysicalNetworksListModel( DefaultListModel< PhysicalNetwork > availablePhysicalNetworksListModel ){ this.availablePhysicalNetworksListModel = availablePhysicalNetworksListModel; }
	
    private JButton addButton;
    public JButton getAddButton(){ return this.addButton; }
    public void setAddButton( JButton addButton ){ this.addButton = addButton; }
    
    private JButton addAllButton;
    public JButton getAddAllButton(){ return this.addAllButton; }
    public void setAddAllButton( JButton addAllButton ){ this.addAllButton = addAllButton; }
    
    private JButton removeButton;
    public JButton getRemoveButton(){ return this.removeButton; }
    public void setRemoveButton( JButton removeButton ){ this.removeButton = removeButton; }
    
    private JButton removeAllButton;
    public JButton getRemoveAllButton(){ return this.removeAllButton; }
    public void setRemoveAllButton( JButton removeAllButton ){ this.removeAllButton = removeAllButton; }
    
	private JList< PhysicalNetwork > selectedPhysicalNetworksList;
	public JList< PhysicalNetwork > getSelectedPhysicalNetworksList(){ return selectedPhysicalNetworksList; }
	public void setSelectedPhysicalNetworksList( JList< PhysicalNetwork > selectedPhysicalNetworksList ){ this.selectedPhysicalNetworksList = selectedPhysicalNetworksList; }
	
	private DefaultListModel< PhysicalNetwork > selectedPhysicalNetworksListModel;
	public DefaultListModel< PhysicalNetwork > getSelectedPhysicalNetworksListModel(){ return selectedPhysicalNetworksListModel; }
	public void getSelectedPhysicalNetworksListModel( DefaultListModel< PhysicalNetwork > selectedPhysicalNetworksListModel ){ this.selectedPhysicalNetworksListModel = selectedPhysicalNetworksListModel; }
    
    public PhysicalNetworksPanel( List< PhysicalNetwork > physicalNetworks )
    {
		this.setAvailablePhysicalNetworksListModel( new DefaultListModel< PhysicalNetwork >() );
		
		for( PhysicalNetwork physicalNetwork: physicalNetworks )
			this.getAvailablePhysicalNetworksListModel().addElement( physicalNetwork );
		
		this.setAvailablePhysicalNetworksList( new JList< PhysicalNetwork >( this.getAvailablePhysicalNetworksListModel() ) );
		this.getAvailablePhysicalNetworksList().setName( PhysicalNetworksPanel.AVAILABLE_LIST );
		this.getAvailablePhysicalNetworksList().setCellRenderer( new PhysicalNetworksListCellRenderer() );
		
		this.setAddButton( new JButton( "Add >>" ) );
		this.getAddButton().setName( PhysicalNetworksPanel.ADD_BUTTON );
		this.getAddButton().setEnabled( false );
		
		this.setAddAllButton( new JButton( "Add All >>" ) );
		this.getAddAllButton().setName( PhysicalNetworksPanel.ADD_ALL_BUTTON );
		this.getAddAllButton().setEnabled( true );
		
		this.setRemoveButton( new JButton( "<< Remove" ) );
		this.getRemoveButton().setName( PhysicalNetworksPanel.REMOVE_BUTTON );
		this.getRemoveButton().setEnabled( false );
		
		this.setRemoveAllButton( new JButton( "<< Remove All" ) );
		this.getRemoveAllButton().setName( PhysicalNetworksPanel.REMOVE_ALL_BUTTON );
		this.getRemoveAllButton().setEnabled( false );

        this.getSelectedPhysicalNetworksListModel( new DefaultListModel< PhysicalNetwork >() );
        this.setSelectedPhysicalNetworksList( new JList< PhysicalNetwork >( this.getSelectedPhysicalNetworksListModel() ) );
        this.getSelectedPhysicalNetworksList().setName( PhysicalNetworksPanel.SELECTED_LIST );
        this.getSelectedPhysicalNetworksList().setCellRenderer( new PhysicalNetworksListCellRenderer() );
		
		this.setLayout( new java.awt.BorderLayout() );
        this.add( this.titlePanel(), BorderLayout.NORTH );
        this.add( this.contentPanel(), BorderLayout.CENTER );
    }
    
	private JPanel titlePanel()
	{
        JLabel titleLabel = new JLabel( "Physical networks" );
        titleLabel.setFont( new Font( "MS Sans Serif", Font.BOLD, 14 ) );
        titleLabel.setBorder( new EmptyBorder( new Insets( 10, 10, 10, 10 ) ) );
        titleLabel.setOpaque( true );
        
        JSeparator separator = new JSeparator();
        
        JPanel titlePanel = new JPanel();
        titlePanel.setLayout( new java.awt.BorderLayout() );
        titlePanel.setBackground( Color.gray );
        titlePanel.add( titleLabel, BorderLayout.CENTER );
        titlePanel.add( separator, BorderLayout.SOUTH );
        
        return titlePanel;
	}
	
	private JPanel contentPanel()
	{
    	JPanel contentPanel = new JPanel();
    	contentPanel.setBorder( new EmptyBorder( new Insets( 50, 50, 50, 50 ) ) );
        contentPanel.add( this.availablePanel() );
        contentPanel.add( this.buttonsPanel() );
        contentPanel.add( this.selectedPanel() );
        
        return contentPanel;
	}
	
	private JPanel availablePanel()
	{
    	JLabel availableLabel = new JLabel( "Available" );
        availableLabel.setFont( new Font( "MS Sans Serif", Font.BOLD, 12 ) );
        availableLabel.setAlignmentX( JPanel.CENTER_ALIGNMENT );
        
		JScrollPane availableScrollPane = new JScrollPane( this.getAvailablePhysicalNetworksList() );
		availableScrollPane.setPreferredSize( new Dimension( 200, 250 ) );
		availableScrollPane.setBorder( BorderFactory.createLineBorder( SystemColor.activeCaption, 2 ) );
				
		JPanel availablePanel = new JPanel();
        availablePanel.setLayout( new BoxLayout( availablePanel, BoxLayout.PAGE_AXIS ) );
        availablePanel.add( availableLabel );
        availablePanel.add( Box.createRigidArea( new Dimension( 0, 5 ) ) );
		availablePanel.add( availableScrollPane );
		
		return availablePanel;
	}
	
	private JPanel buttonsPanel()
	{
		JPanel buttonsPanel = new JPanel();
		buttonsPanel.setLayout( new GridLayout( 0, 1 ) );
		buttonsPanel.add( this.getAddButton() );
		buttonsPanel.add( this.getAddAllButton() );		
		buttonsPanel.add( new JLabel() );
		buttonsPanel.add( this.getRemoveButton() );
		buttonsPanel.add( this.getRemoveAllButton() );
		
		return buttonsPanel;
	}
	
	private JPanel selectedPanel()
	{
		JLabel selectedLabel = new JLabel( "Selected" );
		selectedLabel.setFont( new Font( "MS Sans Serif", Font.BOLD, 12 ) );
		selectedLabel.setAlignmentX( JPanel.CENTER_ALIGNMENT );
		
        JScrollPane selectedScrollPanel = new JScrollPane( this.getSelectedPhysicalNetworksList() );
		selectedScrollPanel.setPreferredSize( new Dimension( 200, 250 ) );
		selectedScrollPanel.setBorder( BorderFactory.createLineBorder( SystemColor.activeCaption, 2 ) );
		
		JPanel selectedPanel = new JPanel();
		selectedPanel.setLayout( new BoxLayout( selectedPanel, BoxLayout.Y_AXIS ) );
		selectedPanel.add( selectedLabel );
        selectedPanel.add( Box.createRigidArea( new Dimension( 0, 5 ) ) );
		selectedPanel.add( selectedScrollPanel );
		
		return selectedPanel;
	}
	
	public void addListeners( ActionListener actionListener, MouseListener mouseListener, ListSelectionListener listSelectionListener )
	{
		this.getAvailablePhysicalNetworksList().addMouseListener( mouseListener );
		this.getAvailablePhysicalNetworksList().addListSelectionListener( listSelectionListener );
		
		this.getAddButton().addActionListener( actionListener );
		this.getAddAllButton().addActionListener( actionListener );
		
		this.getRemoveButton().addActionListener( actionListener );
		this.getRemoveAllButton().addActionListener( actionListener );
		
		this.getSelectedPhysicalNetworksList().addMouseListener( mouseListener );
		this.getSelectedPhysicalNetworksList().addListSelectionListener( listSelectionListener );
    }
	
	public List< PhysicalNetwork > getSelectedPhysicalNetworks()
	{
		List< PhysicalNetwork > selectedPhysicalNetworks = new ArrayList< PhysicalNetwork >();
		
		for( int i = 0; i < this.getSelectedPhysicalNetworksListModel().size(); i++ )
		{
			PhysicalNetwork physicalNetwork = this.getSelectedPhysicalNetworksListModel().get( i );
			physicalNetwork.setSelected( true );
			
			selectedPhysicalNetworks.add( physicalNetwork );
		}
		
		return selectedPhysicalNetworks;
	}
	
	public void mouseDoubleClicked( JList< PhysicalNetwork > physicalNetworksList, int physicalNetworksListIndex )
	{
		PhysicalNetwork physicalNetwork = physicalNetworksList.getModel().getElementAt( physicalNetworksListIndex );
		
		if( physicalNetworksList.getName().equals( PhysicalNetworksPanel.AVAILABLE_LIST ) )
		{
			this.getSelectedPhysicalNetworksListModel().addElement( physicalNetwork );
			this.getAvailablePhysicalNetworksListModel().removeElementAt( physicalNetworksListIndex );
		}
		else
		{
			this.getAvailablePhysicalNetworksListModel().addElement( physicalNetwork );
			this.getSelectedPhysicalNetworksListModel().removeElementAt( physicalNetworksListIndex );
		}
	}
	
	public void buttonClicked( JButton button )
	{
		if( button.getName().equals( PhysicalNetworksPanel.ADD_BUTTON ) )
		{
			for( PhysicalNetwork physicalNetwork: this.getAvailablePhysicalNetworksList().getSelectedValuesList() )
			{
				this.getSelectedPhysicalNetworksListModel().addElement( physicalNetwork );
				this.getAvailablePhysicalNetworksListModel().removeElement( physicalNetwork );
			}
		}
		else if( button.getName().equals( PhysicalNetworksPanel.ADD_ALL_BUTTON ) )
		{
			for( int i = 0; i < this.getAvailablePhysicalNetworksListModel().getSize(); i++ )
				this.getSelectedPhysicalNetworksListModel().addElement( this.getAvailablePhysicalNetworksListModel().getElementAt( i ) );
			
			this.getAvailablePhysicalNetworksListModel().removeAllElements();
		}
		else if( button.getName().equals( PhysicalNetworksPanel.REMOVE_BUTTON ) )
		{
			for( PhysicalNetwork physicalNetwork: this.getSelectedPhysicalNetworksList().getSelectedValuesList() )
			{
				this.getAvailablePhysicalNetworksListModel().addElement( physicalNetwork );
				this.getSelectedPhysicalNetworksListModel().removeElement( physicalNetwork );
			}
		}
		else if( button.getName().equals( PhysicalNetworksPanel.REMOVE_ALL_BUTTON ) )
		{
			for( int i = 0; i < this.getSelectedPhysicalNetworksListModel().getSize(); i++ )
				this.getAvailablePhysicalNetworksListModel().addElement( this.getSelectedPhysicalNetworksListModel().getElementAt( i ) );
			
			this.getSelectedPhysicalNetworksListModel().removeAllElements();
		}
	}
	
	public void updateButtons()
	{
		if( !this.getAvailablePhysicalNetworksList().isSelectionEmpty() )
			this.getAddButton().setEnabled( true );
		else
			this.getAddButton().setEnabled( false );
		
		if( this.getAvailablePhysicalNetworksListModel().getSize() > 0 )
			this.getAddAllButton().setEnabled( true );
		else
			this.getAddAllButton().setEnabled( false );
		
		if( !this.getSelectedPhysicalNetworksList().isSelectionEmpty() )
			this.getRemoveButton().setEnabled( true );
		else
			this.getRemoveButton().setEnabled( false );
		
		if( this.getSelectedPhysicalNetworksListModel().getSize() > 0 )
			this.getRemoveAllButton().setEnabled( true );
		else
			this.getRemoveAllButton().setEnabled( false );
	}
	
}
